﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using static 摸鱼._数据库._方案._步骤;
using static 摸鱼.全局类;
using Newtonsoft.Json;
using JsonIgnoreAttribute = Newtonsoft.Json.JsonIgnoreAttribute;
using System.Globalization;
using OpenCvSharp;
using static 摸鱼._数据库._方案;
using static 摸鱼.核心._数据;
using static 摸鱼.键鼠.钩子;
namespace 摸鱼
{
    public class _数据库 : I数据库
    {
        public _数据库()
        {
            参数.Add(CS.maxThreadCount, new() { 解释 = "", 值 = "30" });
            方法修改列表["找图"] = "模板找图";
            方法修改列表["取色a"] = "取色";
            方法修改列表["移动"] = "直线移动";
        }
        public int 方案ID;
        public int 变量ID;
        public float 数据库版本;
        public Queue<int> 变量闲ID = new();

        public _方案? _当前方案;
        [JsonProperty]
        public _方案? 当前方案 { get => _当前方案; set => _当前方案 = value; }
        public _方案._步骤? _当前步骤;
        [JsonProperty]
        public _方案._步骤? 当前步骤 { get => _当前步骤; set => _当前步骤 = value; }
        public _方法? _当前方法;
        [JsonProperty]
        public _方法? 当前方法 { get => _当前方法; set => _当前方法 = value; }

        [JsonIgnore]
        private _参数? _当前参数;
        public _参数? 当前参数
        {
            get => _当前参数;
            set
            {
                _当前参数 = value;
            }
        }
        private string? _当前变量;
        public string? 当前变量
        {
            get => _当前变量;
            set
            {
                _当前变量 = value;
            }
        }

        public double winW;
        public double winH;
        public double winX;
        public double winY;
        public double[] winRow = [-99, 0, 0];
        public double[] winColumn = new double[7];

        [JsonIgnore]
        public object 选中节点;
        public Dictionary<string, List<double[,]>> 训练模型 = new();
        public Dictionary<Keys, DateTime> 开始快捷键 = new();
        public Dictionary<Keys, DateTime> 结束快捷键 = new();
        public Dictionary<Keys, DateTime> 隐藏快捷键 = new();
        public Dictionary<Keys, DateTime> 截图快捷键 = new();
        public Dictionary<string, _变量> 变量 = new();
        public List<string> 子变量 = new();
        public Dictionary<CS, _参数> 参数 = new() { };

        public List<_方案> 方案 = new();
        public _数据库 版本检查(bool 读档)
        {
            if (数据库版本 == 2.55F)
            {
                if (读档)
                {
                    数据库版本 = 2.55F;
                    return this;
                }
                else
                {
                    return this;
                }
            }
            else
                return this;
        }
        public class _方案 : I数据库
        {
            public string 名字 { get; set; }
            public List<_方案> 父 { get; set; } = new();
            public List<_方案> 子 { get; set; } = new();
            public Dictionary<CS, _参数> 参数 { get; set; } = new();
            public List<string> 子变量 { get; set; } = new();
            public List<_步骤> 步骤 { get; set; } = new();
            public readonly double ID = 时间戳;
            public _方案() { }
            public _方案(string 名)
            {
                名字 = 名;
            }
            public _方案(_方案 原, bool isNewCreate)
            {
                父 = new(原.父);
                名字 = 原.名字;
                foreach (var item in 原.步骤)
                    步骤.Add(new(item, isNewCreate));
                foreach (var item in 原.参数)
                    参数.Add(item.Key, new(item.Value));
                foreach (var item in 原.子)
                    子.Add(new(item, isNewCreate, this));
                if (isNewCreate)
                {
                    子变量.Clear();
                    foreach (var item in 子变量)
                    {
                        string 非数字 = Regex.Replace(item, "\\d", "") + 数据库.变量闲ID.Dequeue();
                        数据库.变量.Add(非数字, new(数据库.变量[item], this));
                        子变量.Add(非数字);
                    }
                }
                else
                    子变量 = new(子变量);
            }
            public _方案(_方案 原, bool isNewCreate, _方案 新父)
            {
                父.Add(新父);
                名字 = 原.名字;
                foreach (var item in 原.步骤)
                    步骤.Add(new(item, isNewCreate));
                foreach (var item in 原.参数)
                    参数.Add(item.Key, new(item.Value));
                foreach (var item in 原.子)
                    子.Add(new(item, isNewCreate, this));
                if (isNewCreate)
                {
                    子变量.Clear();
                    foreach (var item in 子变量)
                    {
                        string 非数字 = Regex.Replace(item, "\\d", "") + 数据库.变量闲ID.Dequeue();
                        数据库.变量.TryAdd(非数字, new(数据库.变量[item], this));
                        子变量.Add(非数字);
                    }
                }
                else
                    子变量 = new(子变量);
            }
            public void Dispose(bool 清空变量原数据)
            {
                if (参数 != null)
                    参数.Clear();
                if (清空变量原数据)
                    foreach (var item in 子变量)
                        数据库.变量.TryRemove(item);
                子变量.Clear();

                父.Clear();
                foreach (var item in 子)
                    item.Dispose(清空变量原数据);
                子.Clear();
                foreach (var item in 步骤)
                    item.Dispose(清空变量原数据);
                步骤.Clear();
                GC.SuppressFinalize(this);
            }
            ~_方案()
            {
                Dispose(false);
            }
            public class _步骤 : I数据库
            {
                public Dictionary<CS, _参数> 参数 { get; set; } = new();
                public List<string> 子变量 { get; set; } = new();
                public List<_方法> 方法 { get; set; } = new();
                public string 名字 { get; set; }
                public readonly double ID = 时间戳;
                public _步骤()
                {
                    名字 = "步骤";
                }
                public _步骤(_步骤 原, bool isNewCreate)
                {
                    名字 = 原.名字;
                    foreach (var item in 原.方法)
                        方法.Add(new(item));
                    foreach (var item in 原.参数)
                        参数.Add(item.Key, new(item.Value));
                    if (isNewCreate)
                    {
                        foreach (var item in 原.子变量)
                        {
                            string 非数字 = Regex.Replace(item, "\\d", "") + 数据库.变量闲ID.Dequeue();
                            数据库.变量.TryAdd(非数字, new(数据库.变量[item], this));
                            子变量.Add(非数字);
                        }
                    }
                    else
                    {
                        子变量 = new(原.子变量);
                        foreach (var item in 子变量)
                            数据库.变量[item] = new(数据库.变量[item], this);
                    }
                }
                public void Dispose(bool 清空变量原数据)
                {
                    if (参数 != null)
                        参数.Clear();
                    if (清空变量原数据)
                        foreach (var item in 子变量)
                            数据库.变量.TryRemove(item);
                    子变量.Clear();

                    foreach (var item in 方法)
                        item.Dispose();
                    方法.Clear();
                    GC.SuppressFinalize(this);
                }
                ~_步骤()
                {
                    Dispose(false);
                }

                public class _方法 : I数据库
                {
                    public string 名字 { get; set; }
                    public List<_方法> 父 { get; set; } = new();
                    public List<_方法> 子 { get; set; } = new();
                    public Dictionary<CS, _参数> 参数 { get; set; } = new();
                    public readonly double ID = 时间戳;
                    public _方法() { }
                    public _方法(string 名)
                    {
                        名字 = 名;
                    }
                    public _方法(_方法 原)
                    {
                        父 = new(原.父);
                        名字 = 原.名字;
                        foreach (var item in 原.子)
                            子.Add(new(item, this));
                        foreach (var item in 原.参数)
                            参数.Add(item.Key, new(item.Value));
                    }
                    public _方法(_方法 原, _方法 新父)
                    {
                        父.Add(新父);
                        名字 = 原.名字;
                        foreach (var item in 原.子)
                            子.Add(new(item, this));
                        foreach (var item in 原.参数)
                            参数.Add(item.Key, new(item.Value));
                    }

                    public void Dispose()
                    {
                        if (父 != null)
                            父.Clear();
                        if (子 != null)
                        {
                            foreach (var item in 子)
                                item.Dispose();
                            子.Clear();
                        }
                        if (参数 != null)
                            参数.Clear();
                        GC.SuppressFinalize(this);
                    }
                    ~_方法()
                    {
                        Dispose();
                    }
                }
            }
        }


        public class _参数
        {
            public string 解释;
            private string _值;
            [JsonProperty]
            public string 值
            {
                get
                {
                    return _值;
                }
                set
                {
                    _值 = value;
                    显示文本 = this.文本值合并();
                }
            }
            [JsonProperty]
            public string 显示文本 { get; set; }
            private string _结果值;
            private string? _变量值;

            public _参数()
            { }
            public _参数(_参数 原参数)
            {
                解释 = 原参数.解释;
                值 = 原参数.值;
            }
            public override bool Equals(object obj)
            {
                // 检查是否为同一个对象的引用  
                if (!(obj == this))
                    return false;

                // 检查是否为同一类型  
                if (obj == null || GetType() != obj.GetType())
                    return false;

                // 转换为当前类型的对象  
                _参数 o = (_参数)obj;
                if (!(解释 == o.解释))
                    return false;
                if (!(值 == o.值))
                    return false;
                return true;
            }

            [JsonIgnore]
            public string 结果值
            {
                get
                {
                    _结果值 = 值.求值();
                    return _结果值;
                }
            }
            public string this[valueType._string index] => 值.求值();
            public int this[valueType._int index] => 值.求值().Toint();
            public bool this[valueType._bool index] => 值.求值() == "1";
            public long this[valueType._long index] => 值.求值().Tolong();
            public byte this[valueType._byte index] => 值.求值().Tobyte();
            public float this[valueType._float index] => 值.求值().Tofloat();
            public double this[valueType._double index] => 值.求值().Todouble();

            [JsonIgnore]
            public string 变量值
            {
                get
                {
                    _变量值 = 值.取值();
                    return _变量值 == "" ? 值 : _变量值;
                }
            }

            [JsonIgnore]
            public int[] 区域s
            {
                get
                {
                    _结果值 = 值.求值();
                    string[] 数组 = _结果值.Split(',');
                    return 数组.Select(x => x.Toint()).ToArray();
                }
            }
            [JsonIgnore]
            public Rectangle 区域rectangle
            {
                get
                {
                    var rect = 区域s;
                    return new(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]);
                }
            }
            [JsonIgnore]
            public System.Drawing.Point 区域point
            {
                get
                {
                    var rect = 区域s;
                    return new(rect[0], rect[1]);
                }
            }
            [JsonIgnore]
            public Rect 区域opencvRect
            {
                get
                {
                    var rect = 区域s;
                    return new(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]);
                }
            }
            [JsonIgnore]
            public Win32.RECT 区域win32RECT
            {
                get
                {
                    var rect = 区域s;
                    return new(rect[0], rect[1], rect[2], rect[3]);
                }
            }
            [JsonIgnore]
            public DateTime Time
            {
                get
                {
                    _结果值 = 值;
                    string format = "yyyy/MM/dd HH:mm";
                    // 使用InvariantCulture来确保格式解析不依赖于当前系统的区域设置
                    MoyuControl.MsgboxThrow(!DateTime.TryParseExact(_结果值, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateTime), "时间格式错误");
                    return dateTime;
                }
            }

            [JsonIgnore]
            public System.Drawing.Point 坐标
            {
                get
                {
                    _结果值 = 值.求值();
                    string[] 数组 = _结果值.Split(',');
                    return new System.Drawing.Point(数组[0].Toint(), 数组[1].Toint());
                }
            }
            [JsonIgnore]
            public OpenCvSharp.Point opencv坐标
            {
                get
                {
                    _结果值 = 值.求值();
                    string[] 数组 = _结果值.Split(',');
                    return new OpenCvSharp.Point(数组[0].Toint(), 数组[1].Toint());
                }
            }

            [JsonIgnore]
            public float 音量 { get => float.Parse(值); }
            public _参数 Clone()
            {
                var newsj = (_参数)this.MemberwiseClone();
                return newsj;
            }


            public static implicit operator string(_参数 实例) => 实例.结果值;
            public void Change(ConcurrentHashSet<_参数> 参数事件s, _方法data 方法data, Action<new参数> 动作, MoyuControl.Form_穿透_置顶 form)
            {
                string oldstr = this.结果值;
                参数事件s.Add(this);
                核心.参数事件s[this] = () =>
                {
                    new参数 newstr = this.结果值;
                    if (!newstr.Value.Equals(oldstr, StringComparison.Ordinal))
                    {
                        oldstr = newstr;
                        form.Post(() =>
                        {
                            if (方法data.控件 != null)
                                动作(newstr);
                        });
                    }
                };
            }
            public void Change(ConcurrentHashSet<_参数> 参数事件s, _方法data 方法data, Action<new参数> 动作)
            {
                string oldstr = this.结果值;
                参数事件s.Add(this);
                核心.参数事件s[this] = () =>
                {
                    new参数 newstr = this.结果值;
                    if (!newstr.Value.Equals(oldstr, StringComparison.Ordinal))
                    {
                        oldstr = newstr;
                        前景窗口.Post(() =>
                        {
                            if (方法data.控件 != null)
                                动作(newstr);
                        });
                    }
                };
            }
            public struct new参数
            {
                public string Value;
                public static implicit operator string(new参数 实例) => 实例.Value;
                public static implicit operator new参数(string 值) => new new参数() { Value = 值 };
            }
        }

        public class _变量
        {
            [JsonProperty(IsReference = true)]
            public _数据库? 全局;
            [JsonProperty(IsReference = true)]
            public _数据库._方案? 方案;
            [JsonProperty(IsReference = true)]
            public _数据库._方案._步骤? 步骤;
            public string? 类型;
            public List<MoyuBitmap>? 图片 = new();
            [JsonIgnore]
            private Func<string> 函数;
            private string? _值;
            [JsonProperty]
            public string? 值
            {
                get
                {
                    if (函数 != null)
                        return 函数();
                    else
                        return _值;
                }
                set
                {
                    _值 = value;
                }
            }

            public _变量(Func<string> 函数)
            {
                this.函数 = 函数;
            }
            public _变量()
            { }
            ~_变量()
            {
                图片.Clear();
            }
            public _变量(_变量 原, _方案 新父)
            {
                方案 = 新父;
                类型 = 原.类型;
                值 = 原.值;
                图片 = new(原.图片);
            }
            public _变量(_变量 原, _步骤 新父)
            {
                步骤 = 新父;
                类型 = 原.类型;
                值 = 原.值;
                图片 = new(原.图片);
            }
            public _变量(_变量 原, _数据库 新父)
            {
                全局 = 新父;
                类型 = 原.类型;
                值 = 原.值;
                图片 = new(原.图片);
            }
            public _变量(_变量 原, object 新父)
            {
                switch (true)
                {
                    case var x when 新父 is _数据库._方案 y:
                        方案 = y;
                        break;
                    case var x when 新父 is _数据库._方案._步骤 y:
                        步骤 = y;
                        break;
                    case var x when 新父 is _数据库 y:
                        全局 = y;
                        break;
                }
                类型 = 原.类型;
                值 = 原.值;
                图片 = new(原.图片);
            }
            public _变量 Clone(bool 解引用)
            {
                if (!解引用)
                    return null;
                var newsj = (_变量)this.MemberwiseClone();
                switch (true)
                {
                    case var x when 步骤 != null:
                        newsj.步骤 = new();
                        break;
                    case var x when 方案 != null:
                        newsj.方案 = new("解引用");
                        break;
                    case var x when 全局 != null:
                        newsj.全局 = new();
                        break;
                }
                newsj.图片 = new(图片);
                return newsj;
            }
        }
    }

    public interface I数据库
    {
    }

    public static class 数据库扩展
    {
        private static bool _全部按下判断(List<int> key事件s, List<int> key目标s, bool keydown)
        {
            int 按键计数 = 0;
            int 按键总数 = key目标s.Count;
            foreach (var 事件item in key事件s)
            {
                foreach (var 目标item in key目标s)
                    if (事件item == 目标item)
                        按键计数++;
            }
            return 按键计数 == 按键总数 && 按键计数 != 0;
        }
        private static bool 逻辑按键判断(List<int> 目标按键副本, List<int> key事件s, bool keydown)
        {
            int 目标按键总数 = 目标按键副本.Count;
            if (目标按键总数 == 0 || !keydown)
                return false;

            int 目标按键计数 = 0;
            foreach (var 按键事件item in key事件s)
            {
                if (目标按键副本.Count == 0)
                    return false;
                for (int i = 0; i < 目标按键副本.Count; i++)
                {
                    if (按键事件item == 目标按键副本[i])
                    {
                        目标按键计数++;
                        目标按键副本.RemoveAt(i);
                        break;
                    }
                    else if (目标按键计数 > 0 && i == (目标按键副本.Count - 1))
                        return false;
                }
            }
            return 目标按键计数 == 目标按键总数;
        }
        private static bool _全部弹起判断(List<int> key事件s, List<int> key目标s, bool keydown)
        {
            foreach (var 事件item in key事件s)
            {
                foreach (var 目标item in key目标s)
                    if (事件item == 目标item)
                        return false;
            }
            return true;
        }

        public static bool 全部按下判断<T>(this List<int> key事件s, Dictionary<Keys, T> key目标s, bool keydown)
        {
            return _全部按下判断(key事件s, key目标s.Keys.ToInt(), keydown);
        }
        public static bool 全部按下判断<T>(this List<int> key事件s, Dictionary<int, T> key目标s, bool keydown)
        {
            return _全部按下判断(key事件s, [.. key目标s.Keys], keydown);
        }
        public static bool 全部按下判断(this List<int> key事件s, List<Keys> key目标s, bool keydown)
        {
            return _全部按下判断(key事件s, key目标s.ToInt(), keydown);
        }
        public static bool 全部按下判断(this List<int> key事件s, List<int> key目标s, bool keydown)
        {
            return _全部按下判断(key事件s, key目标s, keydown);
        }
        public static bool 全部按下_符合逻辑顺序<T>(this List<int> key事件s, Dictionary<Keys, T> key目标s, bool keydown)
        {
            return 逻辑按键判断(new List<Keys>(key目标s.Keys).ToInt(), key事件s, keydown);
        }
        public static bool 全部按下_符合逻辑顺序<T>(this List<int> key事件s, Dictionary<int, T> key目标s, bool keydown)
        {
            return 逻辑按键判断(new(key目标s.Keys), key事件s, keydown);
        }
        public static bool 全部按下_符合逻辑顺序(this List<int> key事件s, List<int> key目标s, bool keydown)
        {
            return 逻辑按键判断(key目标s, key事件s, keydown);
        }
        public static bool 全部弹起判断<T>(this List<int> key事件s, Dictionary<Keys, T> key目标s, bool keydown)
        {
            return _全部弹起判断(key事件s, key目标s.Keys.ToInt(), keydown);
        }
        public static bool 全部弹起判断<T>(this List<int> key事件s, Dictionary<int, T> key目标s, bool keydown)
        {
            return _全部弹起判断(key事件s, new(key目标s.Keys), keydown);
        }
        public static bool 全部弹起判断(this List<int> key事件s, List<int> key目标s, bool keydown)
        {
            return _全部弹起判断(key事件s, key目标s, keydown);
        }
    }
}


public enum CS : short
{
    坐标, 找图限时, 图片1, 图片2, 相似度1, 相似度2, 相似度3, 帧率, 开始键, 结束键, 截图键, 隐藏键, 单击次数, 单击间隔, 识图线程数量, 图片压缩, 识图帧数, 符合图片,
    区域, 按住松开时间, 移动时间, 符合度, 时长, 全局音量, 判断变量, 循环变量1, 循环变量2, 音源, 音量, 代码, 代码2, 相对距离, 相对坐标, 鼠标位置, 屏蔽区域, 屏蔽时长,
    目标区域, 跳转步骤, 方法返回值, 窗口句柄, 句柄, 截屏间隔, 线程锁, 色块1面积, 色块2面积, 色块间距, 找双色返回坐标, 框选目标, 鼠标特征码1, 鼠标特征码2,
    鼠标滚轮步长, 键盘按键, 键盘按键2, 鼠标按键, 文本1, 文本2, 前景色, 背景色, 字体大小, 字体加粗, 字体, 调用方案, 方案返回值, 持续触发, 变量1, 变量2, 变量3,
    学习率, 层数, 尺寸, 文件, 类型1, 类型2, 类型3, 数字1, 数字2, 布尔值, 布尔值2, 布尔值3, 异步, 前摇, 时分, 时间, 初始启动方案, 半径, 长度, 角度, 暗号,
    消息, 方法名, 执行时选中, 等待时长, maxThreadCount, 形状, 面积, 面积2, 面积精度, H, S, V, 坐标2, 找所有图, 找所有色, 说明, 特征检测器, 区域2, 数字3, 数字4
}
public enum 层级
{
    None, 方案, 步骤, 方法, 参数, 变量, 数据, 线程
}
